package com.elcom.roaming.module.synthesis.match;

import java.sql.SQLException;

import org.slf4j.Logger;

import com.elcom.roaming.common.StringCouple;
import com.elcom.roaming.common.db.DBQuery;
import com.elcom.roaming.common.db.cache.CacheInsert;
import com.elcom.roaming.common.util.match.Matching;
import com.elcom.roaming.common.util.match.MatchingObjects;
import com.elcom.roaming.module.synthesis.lb.OutputService;

public class MSRNMatchingObjects extends MatchingObjects{

	private CacheInsert cacheInsert;
	private DBQuery dbQuery;
	private OutputService output;
	
	public MSRNMatchingObjects(Logger logger, String name, CacheInsert cacheInsert, DBQuery dbQuery, OutputService output) {
		super(logger, name);
		this.cacheInsert = cacheInsert;
		this.dbQuery = dbQuery;
		this.output = output;
	}

	public void match(MSRNMessage msg){
		if (((MSRNKey) msg.getKey()).type == MSRNKey.PRN) {
			MSRNValue value = (MSRNValue) msg.getValue();
			if (value.called != null) {
				// insert imsi, msisdn into db
				logger.info("Forward to insert cache: " + msg.toString());
				cacheInsert.put(new StringCouple(StringCouple.TYPE_IMSI, value.imsi, StringCouple.TYPE_MSISDN, value.called));
			}
		}

		// matching 
		int code = MatchingObjects.NOT_FOUND_PUT;
		try {
			code = matchObject(msg, getMap());
		} catch (Exception e) {
			logger.error("Matching error: " + msg.toString(), e);
		}

		if ( code == MatchingObjects.FOUND_FORWARD ) {
			logger.info("Drop found: " + msg.toString());
			forward(msg);
		} else if ( code == MatchingObjects.NOT_FOUND_PUT ) {
			logger.info("Put into MSRN HashMap: " + msg.toString());
		} else if ( code == MatchingObjects.MAP_FULL ) {
			logger.error("REJECTED - Matching Map is full: " + msg.toString());
		}
	}
	
	private void forward(MSRNMessage msg) {
		MSRNValue value = (MSRNValue) msg.getValue();
		MSRNValue dropValue = (MSRNValue) msg.getDropValue();
		
		String calling = value.calling != null ? value.calling : dropValue.calling;
		String imsi = value.imsi != null ? value.imsi : dropValue.imsi;
		String called = value.called != null ? value.called : dropValue.called;
		
		if (called != null) {
			// msisdn called found => insert to db & send direct to LB
//			logger.info("Forward to insert cache: " + msg.toString());
//			cacheInsert.put(new StringCouple(StringCouple.TYPE_IMSI, imsi, StringCouple.TYPE_MSISDN, called));
			logger.info("Forward to output queue direct: [calling="+calling + "|called=" + called + "] - " + msg.toString());
			output.put(new StringCouple(StringCouple.TYPE_CALLING, calling, StringCouple.TYPE_MSISDN, called));
		} else {
			// search called in cacheUpdate with key=imsi
			try {
				called = dbQuery.searchMSISDN(imsi);
				if (called != null) {
					logger.info("Forward to output queue indirect: [calling="+calling + "|called=" + called + "] - " + msg.toString());
					output.put(new StringCouple(StringCouple.TYPE_CALLING, calling, StringCouple.TYPE_MSISDN, called));
				} else {
					logger.info("No MSISDN found for imsi: " + msg.toString());
				}
			} catch (SQLException e) {
				logger.info("No MSISDN found for imsi: " + msg.toString());
//				logger.error("Query fail: searchMSISDN(" + imsi + "): " + msg.toString(), e);
			} catch (InterruptedException e) {
				logger.error("Query fail: searchMSISDN(" + imsi + "): " + msg.toString(), e);
			}
		}
	}

	@Override
	public Matching getMatching() {
		return null;
	}
	
	

}
